import os.path
from bdtime import tt
# import pydirectinput
from tools.utils import mouse_move
import mouse
import pandas as pd
import os
import numpy as np
import pyautogui


def run_warm_up(dx=30, _init_position=None, interval=1):
    if _init_position is None:
        _init_position = mouse.get_position()[0]
    else:
        mouse.move(_init_position, screen_height // 2)

    delta_0, delta_1, delta_mean, rate_d0_dm, rate_dx_dm, total_dx, rate_td_dx, cost_t = test_rel_move(dx)
    # prediction_1 = loaded_model.predict([[0, delta_0]])

    tt.sleep(interval / 2)

    delta_0, delta_1, delta_mean, rate_d0_dm, rate_dx_dm, total_dx, rate_td_dx, cost_t = test_rel_move(-dx)
    # prediction_2 = loaded_model.predict([[1, delta_0]])
    # print('predictions ---', prediction_1, prediction_2, 'dx:', dx)

    mouse.move(_init_position, screen_height // 2)
    mouse.click(mouse.MIDDLE)
    # mouse.press(mouse.MIDDLE)
    # tt.sleep(0.1)
    # mouse.release(mouse.MIDDLE)

    tt.sleep(interval / 2)


def test_rel_move(dx=100, init_position=None, run_times=1, interval=0.0, recurrent=False):
    dy = 0
    if init_position is None:
        init_position = mouse.get_position()
        # init_position = pydirectinput.position()
    else:
        mouse.move(*init_position)
    # print('init_position:', init_position)
    # tt.sleep(1)

    if recurrent:
        run_times *= 2

    x_ls = []
    tt.__init__()
    for i in range(run_times):
        if tt.stop_alt('x'):
            raise EOFError('*** stop by user!')

        if recurrent:
            if i % 2 == 0:
                mouse_move(dx, -dy)
                # pydirectinput.moveRel(xOffset=dx, yOffset=-dy, relative=True)
                x = mouse.get_position()[0]
            else:
                mouse_move(-dx, dy)
                # pydirectinput.moveRel(xOffset=-dx, yOffset=dy, relative=True)
                x = mouse.get_position()[0]
        else:
            mouse_move(dx, -dy)
            # pydirectinput.moveRel(xOffset=dx, yOffset=-dy, relative=True)
            x = mouse.get_position()[0]

        # print(i, '---', x, tt.now(5))

        if x not in x_ls:
            x_ls.append(x)

        tt.sleep(interval)

    delta_ls = [i - j for i, j in list(zip(x_ls[1:], x_ls[:-1]))]

    # print('=== dx:', dx)
    end_position = mouse.get_position()[0]
    total_dx = end_position - init_position[0]
    rate_td_dx = round(total_dx / dx, 4) if dx != 0 else 0
    print('--- dx:', dx, 'init_position:', init_position[0], '--> end_position:', end_position, ', total_dx:', total_dx,
          ', rate_td_dx:', rate_td_dx)
    # print('x_ls:', x_ls)
    delta_total = x_ls[-1] - x_ls[0]
    delta_mean = abs(delta_total / (len(x_ls) - 1)) if len(x_ls) > 1 else 0
    # print('x_ls:', x_ls, '--- delta_total:', delta_total, '--- delta_mean:', round(delta_mean, 2), "--- delta_ls:",
    #       delta_ls)

    cost_t = tt.now(5)
    print('cost_t:', cost_t)

    delta_0 = x_ls[0] - init_position[0]

    if recurrent:
        # delta_1 = init_position[0] - x_ls[1]
        # delta_m = abs(x_ls[1] - x_ls[0])
        delta_1 = delta_mean - delta_0
    else:
        delta_1 = delta_mean - delta_0

    rate_dx_dm = dx / delta_mean if delta_mean else 0
    rate_d0_dm = delta_0 / delta_mean if delta_mean else 0
    if len(x_ls) > 1:
        print('--- dx:', dx, '--- delta_0:', delta_0, ', delta_1:', delta_1,
              ', delta_mean:', delta_mean, ', delta_0/delta_mean:', round(rate_d0_dm, 5), ', dx/delta_mean:',
              round(rate_dx_dm, 5))
    else:
        print('--- dx:', dx, '--- delta_0:', delta_0)
    return delta_0, delta_1, delta_mean, rate_d0_dm, rate_dx_dm, total_dx, rate_td_dx, cost_t


def get_df_data(dx_range, dx_length, init_position=None, seed=1, save=True):
    run_times = 1
    interval = 0
    # recurrent = True
    recurrent = False

    _interval = 0.001

    if seed:
        np.random.seed(seed)
    dx_ls = np.random.randint(-dx_range, dx_range, dx_length)
    _init_position = mouse.get_position()[0]

    init_position = init_position if init_position else mouse.get_position()
    # init_position = None
    tt.sleep(1)

    columns = ['i', 'dx', 'delta_0', 'rate_td_dx', 'dt']
    df = pd.DataFrame([], columns=columns)

    from bdtime import Time
    tx = Time()
    num_t_decimal = 6
    total_i = len(dx_ls)
    for i in range(len(dx_ls)):
        t0 = tx.now(num_t_decimal)

        dx = dx_ls[i]
        if tt.stop_alt('x'):
            raise EOFError("stop!!")

        print(f'\n=== i: {i} / {total_i}')

        if init_position:
            mouse.move(*init_position)
        tt.sleep(_interval)

        delta_0, delta_1, delta_mean, rate_d0_dm, rate_dx_dm, total_dx, rate_td_dx, cost_t = test_rel_move(
            dx, init_position, run_times, interval, recurrent)

        # row = pd.DataFrame([[i, dx, delta_0, delta_1, delta_mean, rate_d0_dm, rate_dx_dm, total_dx]], columns=columns)

        t1 = tx.now(num_t_decimal)
        dt = t1 - t0
        row = pd.DataFrame([[i, dx, delta_0, rate_td_dx, dt]], columns=columns)

        df = pd.concat([df, row], ignore_index=True)
    end_position = mouse.get_position()[0]
    total_dx = end_position - _init_position
    print(f'\n~~~ init_position: {_init_position} --> end_position:', end_position, ', total_dx:', total_dx)

    timestamp = tt.get_current_beijing_time_str(tt.common_date_time_formats.s_int)
    f_name = f'{timestamp}__{dx_range}__{dx_length}__{_interval}__{seed}'
    print('--- f_name --- {dx_range}__{dx_length}__{_interval}__{timestamp}__{seed}:', f_name)

    dir_name = os.path.join('../tempdir', 'df')
    os.makedirs(dir_name, exist_ok=True)

    f_path = os.path.join(dir_name, f'{f_name}.csv')

    if save:
        df.to_csv(f_path, index=False)
    return df


screen_width, screen_height = pyautogui.size()


def main():
    save = True
    # dx_range = 50
    dx_length = 100
    seed = 1
    # dx_range_ls = np.arange(1, 15, 1)
    # dx_range_ls = np.arange(10, 50, 5)
    # dx_range_ls = np.arange(50, 120, 10)
    # dx_range_ls = np.arange(100, 300, 10)
    # dx_range_ls = np.arange(500, 1000, 100)
    # dx_range_ls = np.arange(400, 600, 50)
    dx_range_ls = [100]

    init_position = 1000, 500
    # init_position = screen_width // 2, screen_height // 2

    run_warm_up()

    df_ls = []
    total = len(dx_range_ls)
    for i in range(len(dx_range_ls)):
        dx_range = dx_range_ls[i]
        if tt.stop_alt('x'):
            raise EOFError("stop!!!")

        print(f'~~~~~~~ i: {i} / {total}')
        tt.sleep(1)

        df_i = get_df_data(dx_range, dx_length, init_position=init_position, seed=seed, save=save)
        df_ls.append(df_i)
    return df_ls


if __name__ == '__main__':
    main()
